home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
fstwrt4.zip
/
FASTWR.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-04
|
19KB
|
439 lines
; FASTWR.ASM
; Fast screen writing routines
; By Brian Foley
; Last update: 11/08/87
;****************************************************** Equates
Mono = 0
CGA = 1
EGA = 2
MCGA = 3
VGA = 4
;****************************************************** Data
DATA SEGMENT BYTE PUBLIC
EXTRN BaseOfScreen : WORD ;Pascal variables
EXTRN WaitForRetrace : BYTE
CurrentMode DB ? ;local variables
Display DB ?
DATA ENDS
;****************************************************** Code
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE,DS:DATA
PUBLIC FastWrite, FastWriteNA, ChangeAttribute, MoveFromScreen
PUBLIC MoveToScreen, CurrentDisplay, CurrentVideoMode
;****************************************************** CalcOffset
;Calculates offset in video memory corresponding to Row,Column
;On entry, CH has Row, BX has Column (both 1-based)
;On exit, ES:DI points to proper address in video memory, AX = 0
CalcOffset PROC NEAR
XOR AX,AX ;AX = 0
MOV CL,AL ;CL = 0
MOV BH,AL ;BH = 0
DEC CH ;Row (in CH) to 0..24 range
SHR CX,1 ;CX = Row * 128
MOV DI,CX ;Store in DI
SHR DI,1 ;DI = Row * 64
SHR DI,1 ;DI = Row * 32
ADD DI,CX ;DI = (Row * 160)
DEC BX ;Col (in BX) to 0..79 range
SHL BX,1 ;Account for attribute bytes
ADD DI,BX ;DI = (Row * 160) + (Col * 2)
MOV ES,BaseOfScreen ;ES:DI points to BaseOfScreen:Row,Col
RET ;Return
CalcOffset ENDP
;****************************************************** FastWrite
;procedure FastWrite(St : String; Row, Col, Attr : Byte);
;Write St at Row,Col in Attr (video attribute) without snow
;equates for parameters:
FWAttr EQU BYTE PTR [BP+6]
FWCol EQU BYTE PTR [BP+8]
FWRow EQU BYTE PTR [BP+10]
FWSt EQU DWORD PTR [BP+12]
FastWrite PROC FAR
PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV CH,FWRow ;CH = Row
MOV BL,FWCol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
MOV CL,WaitForRetrace ;Grab this before changing DS
LDS SI,FWSt ;DS:SI points to St[0]
CLD ;Set direction to forward
LODSB ;AX = Length(St); DS:SI -> St[1]
XCHG AX,CX ;CX = Length; AL = WaitForRetrace
JCXZ FWExit ;If string empty, exit
MOV AH,FWAttr ;AH = Attribute
RCR AL,1 ;If WaitForRetrace is False...
JNC FWMono ; use "FWMono" routine
MOV DX,03DAh ;Point DX to CGA status port
FWGetNext:
LODSB ;Load next character into AL
; AH already has Attr
MOV BX,AX ;Store video word in BX
CLI ;No interrupts now
FWWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Vertical retrace in progress?
JNZ FWStore ;If so, go
RCR AL,1 ;Else, wait for end of
JC FWWaitNoH ; horizontal retrace
FWWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC FWWaitH ; retrace
FWStore:
MOV AX,BX ;Move word back to AX...
STOSW ; and then to screen
STI ;Allow interrupts!
LOOP FWGetNext ;Get next character
JMP FWExit ;Done
FWMono:
LODSB ;Load next character into AL
; AH already has Attr
STOSW ;Move video word into place
LOOP FWMono ;Get next character
FWExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return
FastWrite ENDP
;****************************************************** FastWriteNA
;procedure FastWriteNA(St : String; Row, Col : Byte);
;Write St at Row,Col without snow, and don't change video attributes
;equates for parameters:
FNCol EQU BYTE PTR [BP+6]
FNRow EQU BYTE PTR [BP+8]
FNSt EQU DWORD PTR [BP+10]
FastWriteNA PROC FAR
PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV CH,FNRow ;CH = Row
MOV BL,FNCol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
MOV CL,WaitForRetrace ;Grab this before changing DS
LDS SI,FNSt ;DS:SI points to St[0]
CLD ;Set direction to forward
LODSB ;AX = Length(St); DS:SI -> St[1]
XCHG AX,CX ;CX = Length; AL = Wait
JCXZ FNExit ;If string empty, exit
RCR AL,1 ;If WaitForRetrace is False...
JNC FNNoWait ; use FNNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
FNGetNext:
LODSB ;Load next character into AL
MOV AH,AL ;Store char in AH
CLI ;No interrupts now
FNWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ FNStore ; In progress? go
RCR AL,1 ;Else, wait for end of
JC FNWaitNoH ; horizontal retrace
FNWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC FNWaitH ; retrace
FNStore:
MOV AL,AH ;Move char back to AL...
STOSB ; and then to screen
STI ;Allow interrupts
INC DI ;Skip attribute bytes
LOOP FNGetNext ;Get next character
JMP FNExit ;Done
FNNoWait:
MOVSB ;Move character to screen
INC DI ;Skip attribute bytes
LOOP FNNoWait ;Get next character
FNExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 8 ;Remove parameters and return
FastWriteNA ENDP
;****************************************************** ChangeAttribute
;procedure ChangeAttribute(Number : Word; Row, Col, Attr : Byte);
;Change Number video attributes to Attr starting at Row,Col
;equates for parameters:
CAAttr EQU BYTE PTR [BP+6]
CACol EQU BYTE PTR [BP+8]
CARow EQU BYTE PTR [BP+10]
CANumber EQU WORD PTR [BP+12]
ChangeAttribute PROC FAR
PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
MOV CH,CARow ;CH = Row
MOV BL,CACol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
INC DI ;Skip character
CLD ;Set direction to forward
MOV CX,CANumber ;CX = Number to change
JCXZ CAExit ;If zero, exit
MOV AL,CAAttr ;AL = Attribute
CMP WaitForRetrace,1 ;Get wait state
JNE CANoWait ;If WaitForRetrace is False
; use CANoWait routine
MOV AH,AL ;Store attribute in AH
MOV DX,03DAh ;Point DX to CGA status port
CAGetNext:
CLI ;No interrupts now
CAWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vert. retrace
JNZ CAGo ;In progress? Go
RCR AL,1 ;Wait for end of horizontal
JC CAWaitNoH ; retrace
CAWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC CAWaitH ; retrace
CAGo:
MOV AL,AH ;Move Attr back to AL...
STOSB ; and then to screen
STI ;Allow interrupts
INC DI ;Skip characters
LOOP CAGetNext ;Look for next opportunity
JMP CAExit ;Done
CANoWait:
STOSB ;Change the attribute
INC DI ;Skip characters
LOOP CANoWait ;Get next character
CAExit: ;Next instruction
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 8 ;Remove parameters and return
ChangeAttribute ENDP
;****************************************************** MoveFromScreen
;procedure MoveFromScreen(var Source, Dest; Length : Word);
;Move Length words from Source (video memory) to Dest without snow
;equates for parameters:
MFLength EQU WORD PTR [BP+6]
MFDest EQU DWORD PTR [BP+8]
MFSource EQU DWORD PTR [BP+12]
MoveFromScreen PROC FAR
PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
MOV BX,DS ;Save DS in BX
MOV AL,WaitForRetrace ;Grab before changing DS
LES DI,MFDest ;ES:DI points to Dest
LDS SI,MFSource ;DS:SI points to Source
MOV CX,MFLength ;CX = Length
CLD ;Set direction to forward
RCR AL,1 ;Check WaitForRetrace
JNC MFNoWait ;False? Use MFNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
MFNext:
CLI ;No interrupts now
MFWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ MFGo ;In progress? go
RCR AL,1 ;Wait for end of horizontal
JC MFWaitNoH ; retrace
MFWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC MFWaitH ; retrace
MFGo:
LODSW ;Load next video word into AX
STI ;Allow interrupts
STOSW ;Store video word in Dest
LOOP MFNext ;Get next video word
JMP MFExit ;All Done
MFNoWait:
REP MOVSW ;That's it!
MFExit:
MOV DS,BX ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return
MoveFromScreen ENDP
;****************************************************** MoveToScreen
;procedure MoveToScreen(var Source, Dest; Length : Word);
;Move Length words from Source to Dest (video memory) without snow
;equates for parameters:
MTLength EQU WORD PTR [BP+6]
MTDest EQU DWORD PTR [BP+8]
MTSource EQU DWORD PTR [BP+12]
MoveToScreen PROC FAR
PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV AL,WaitForRetrace ;Grab before changing DS
LES DI,MTDest ;ES:DI points to Dest
LDS SI,MTSource ;DS:SI points to Source
MOV CX,MTLength ;CX = Length
CLD ;Set direction to forward
RCR AL,1 ;Check WaitForRetrace
JNC MTNoWait ;False? Use MTNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
MTGetNext:
LODSW ;Load next video word into AX
MOV BX,AX ;Store video word in BX
CLI ;No interrupts now
MTWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ MTGo ;In progress? Go
RCR AL,1 ;Wait for end of horizontal
JC MTWaitNoH ; retrace
MTWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC MTWaitH ; retrace
MTGo:
MOV AX,BX ;Move word back to AX...
STOSW ; and then to screen
STI ;Allow interrupts
LOOP MTGetNext ;Get next video word
JMP MTExit ;All done
MTNoWait:
REP MOVSW ;That's all!
MTExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return
MoveToScreen ENDP
;****************************************************** CurrentModePrim
;Returns current video mode in AL
CurrentModePrim PROC NEAR
MOV AH,0Fh ;Get video mode function
INT 10h ;Call BIOS
MOV CurrentMode,AL ;Save it
RET ;Return
CurrentModePrim ENDP
;****************************************************** CurrentDisplay
;function CurrentDisplay : DisplayType;
;Returns type of the currently active display.
JunkValue = 0FFFFh
CurrentDisplay PROC FAR
;get the current video mode
CALL CurrentModePrim ;Call primitive routine
;test for VGA
MOV Display,VGA ;Assume VGA
MOV CX,JunkValue ;Load CX with junk value
MOV AX,1C00h ;Save/Restore video state
INT 10h
CMP AL,1Ch ;AL = $1C signals valid call
JE CDexit ;Adapter type known
;test for MCGA
MOV Display,MCGA ;Assume MCGA
MOV BL,32h ;Choose Enable
MOV AX,1200h ;Enable/Disable video addressing
INT 10h
CMP AL,12h ;AL = $12 signals valid call
JE CDexit ;Adapter type known
;test for EGA
MOV Display,EGA ;Assume EGA
MOV BX,0FF10h ;Return EGA information
MOV CX,JunkValue ;Load CX with junk value
MOV AX,1200h ;Alternate function select
INT 10h
XOR AL,AL ;AL = 0
CMP CX,JunkValue ;CX unchanged?
JE CDplain ;If so, not an EGA
CMP BH,1 ;BH should be 0 or 1
JA CDplain ;Mono or CGA if it isn't
;See if EGA is the active display
CMP BH,1 ;mono display?
JE CDegaMono ;If so, use mono check
CMP CurrentMode,7 ;In mono mode?
JE CDplain ;If so, we're not on the EGA
JMP SHORT CDexit ;else, it's an EGA
CDegaMono:
CMP CurrentMode,7 ;Current mode = 7?
JNE CDplain ;Exit if not
CDexit:
MOV AL,Display ;set return value
RET ;Return
CDplain:
MOV Display,CGA ;Assume CGA
CMP CurrentMode,7 ;Mono mode
JNE CDexit ;Done if not
MOV Display,Mono ;Else, Mono
JMP SHORT CDexit ;Done
CurrentDisplay ENDP
;****************************************************** CurrentVideoMode
;function CurrentVideoMode : Byte;
;Returns current video mode in AL
CurrentVideoMode PROC FAR
CALL CurrentModePrim ;Call primitive routine
RET ;Return
CurrentVideoMode ENDP
CODE ENDS
END